﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using Expect.Core.Interfaces;

namespace Expect.Core.IO
{
    /// <summary>
    /// Writer implementation for text format
    /// </summary>
    public class TextSpecificationWriter : TextSpecification, ISpecificationWriter
    {
        /// <summary>
        /// Write a specification in a stream
        /// </summary>
        /// <param name="stream">
        /// The stream to write in
        /// </param>
        /// <param name="definition">
        /// The specification to write
        /// </param>
        /// <param name="renderExecutionResult">
        /// indicate if the execution result should be written
        /// </param>
        /// <param name="renderStandalone">
        /// indicate if the specification is rendered alone. If false, it means that the specification is rendered with other specification.
        /// If standalone, the specification must render with headers and footers
        /// </param>
        public void Write(Stream stream, SpecificationDefinition definition, bool renderExecutionResult, bool renderStandalone)
        {
            using (StreamWriter writer = new StreamWriter(stream))
            {
                WriteSpecificationDefinition(writer, definition);
                foreach (var fixture in definition)
                {
                    WriteFixture(writer, fixture);
                }
            }
        }

        private void WriteSpecificationDefinition(StreamWriter writer, SpecificationDefinition definition)
        {
            if (definition.HasClass)
            {
                //WriteDefinition(writer, definition.ClassName, definition.Arguments);
            }
        }

        private void WriteFixture(StreamWriter writer, FixtureDefinition fixture)
        {
            writer.WriteLine("");
            
            if (fixture.HasClass)
            {
                WriteFixtureRow(writer, fixture.Definition);
            }

            // if (fixture.Definition != null && fixture.Definition.Count > 0)
            //    WriteFixtureRow(writer, fixture.Definition);
            
            foreach (var row in fixture)
            {
                WriteFixtureRow(writer, row);
            }            
        }

        private void WriteDefinition(StreamWriter writer, string name, FixtureRow arguments)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(name);

            if (arguments != null && arguments.Count > 0)
            {
                for (int i = 0; i < arguments.Count; i++)
                {
                    sb.Append(" " + CellSeparator + " ");
                    sb.Append(arguments[i].Text);
                }
            }

            writer.WriteLine(sb.ToString());
        }

        private void WriteFixtureRow(StreamWriter writer, FixtureRow row)
        {
            StringBuilder sb = new StringBuilder();
            
            for(int i=0 ; i<row.Count ; i++)
            {
                if (i > 0)
                    sb.Append(" " + CellSeparator + " ");

                sb.Append(row[i].Text);                
            }

            writer.WriteLine(sb.ToString());
        }

        private void WriteComment(StreamWriter writer, string text)
        {
            if (!string.IsNullOrEmpty(text))
            {
                string[] lines = text.Split('\r');
                foreach (string s in lines)
                {
                    string line = s.Trim();
                    if (!string.IsNullOrEmpty(line))
                        writer.WriteLine(CommentToken + line);
                }
            }
        }
    }
}
